home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / fastimg.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  16KB  |  779 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *       fastimg -
  19.  *        Faster copies between long pixel data and image files.
  20.  *    This could be done on top of the iris image library, but the
  21.  *    performance is lower by a factor of two of so.
  22.  *
  23.  *      This code should work on machines with any byte order.
  24.  *
  25.  *    Could someone make this run real fast using multiple processors?
  26.  *
  27.  *                Paul Haeberli - 1991
  28.  */
  29.  
  30. /*
  31.  *    Memory mapped file routines
  32.  *
  33.  */
  34. #include <stdio.h>
  35. #include <resource.h>
  36.  
  37. #include <sys/types.h>
  38. #include <sys/mman.h>
  39. #include <sys/stat.h>
  40.  
  41. typedef struct MFILE {
  42.     unsigned char *paddr;
  43.     unsigned char *fpos;
  44.     int flen;
  45.     FILE *file;
  46. } MFILE;
  47.  
  48. static MFILE *mfopen(name,mode)
  49. char *name;
  50. char *mode;
  51. {
  52.     int fd, i;
  53.     struct stat sb;
  54.     MFILE *mf;
  55.  
  56.     if(mode[0] == 'r') {
  57.     if(name[0] == '#') {
  58.         mf = (MFILE *)malloc(sizeof(MFILE));
  59.         mf->file = res_fopen(name,"r");
  60.         if(mf->file)
  61.             return mf;
  62.         else
  63.         return 0;
  64.     } 
  65.     fd = open(name,0);
  66.     if(fd<0) 
  67.         return 0;
  68.     fstat(fd,&sb);
  69.     mf = (MFILE *)malloc(sizeof(MFILE));
  70.     mf->flen = sb.st_size;
  71.     mf->paddr = (unsigned char *)mmap(0,mf->flen,PROT_READ,MAP_SHARED,fd,0);
  72.     mf->file = 0;
  73.     close(fd);
  74.     if(!mf->paddr) 
  75.         return 0;
  76.     mf->fpos = mf->paddr;
  77.     return mf;
  78.     } else {
  79.     fprintf(stderr,"not done yet\n");
  80.     return 0;
  81.     }
  82. }
  83.  
  84. static unsigned char *rbuf;
  85. static unsigned int rbuflen;
  86.  
  87. static unsigned char *mfread(mf,n)
  88. MFILE *mf;
  89. int n;
  90. {
  91.     unsigned char *ret;
  92.  
  93.     if(mf->file) {
  94.     if(!rbuf) {
  95.             rbuf = (unsigned char *)malloc(n);
  96.         rbuflen = n;
  97.     } else if (rbuflen<n) {
  98.              rbuf = (unsigned char *)realloc(rbuf,n);
  99.         rbuflen = n;
  100.     }
  101.     res_fread(rbuf,n,1,mf->file);
  102.     return rbuf;
  103.     } else {
  104.     ret = mf->fpos;
  105.     mf->fpos += n;
  106.     return ret;
  107.     }
  108. }
  109.  
  110. static mfseek(mf,pos)
  111. MFILE *mf;
  112. int pos;
  113. {
  114.     if(mf->file) {
  115.     res_fseek(mf->file,pos,SEEK_SET);
  116.     } else
  117.     mf->fpos = mf->paddr+pos;
  118. }
  119.  
  120. static mfclose(mf)
  121. MFILE *mf;
  122. {
  123.     if(mf->file)
  124.       res_fclose(mf->file);
  125.     else
  126.     munmap(mf->paddr,mf->flen);
  127.     free(mf);
  128. }
  129.  
  130. #include "image.h"
  131. #include "unistd.h"
  132. #include "lum.h"
  133.  
  134. #define OFFSET_R    3    /* this is byte order dependent */
  135. #define OFFSET_G    2
  136. #define OFFSET_B    1
  137. #define OFFSET_A    0
  138.  
  139. #define CHANOFFSET(z)    (3-(z))    /* this is byte order dependent */
  140.  
  141. static expandrow();
  142. static setalpha();
  143. static copybw();
  144. static interleaverow();
  145. static int compressrow();
  146. static lumrow();
  147.  
  148. #define TAGLEN    (5)
  149.  
  150. /*
  151.  *    addlongimgtag - 
  152.  *        this is used to extract image data from core dumps.
  153.  *
  154.  */
  155. addlongimgtag(dptr,xsize,ysize)
  156. unsigned long *dptr;
  157. int xsize, ysize;
  158. {
  159.     dptr = dptr+(xsize*ysize);
  160.     dptr[0] = 0x12345678;
  161.     dptr[1] = 0x59493333;
  162.     dptr[2] = 0x69434222;
  163.     dptr[3] = xsize;
  164.     dptr[4] = ysize;
  165. }
  166.  
  167. /*
  168.  *    byte order independent read/write of shorts and longs.
  169.  *
  170.  */
  171. static unsigned short getshort(inf)
  172. MFILE *inf;
  173. {
  174.     unsigned char *buf;
  175.  
  176.     buf = mfread(inf,2);
  177.     return (buf[0]<<8)+(buf[1]<<0);
  178. }
  179.  
  180. static unsigned long getlong(inf)
  181. MFILE *inf;
  182. {
  183.     unsigned char *buf;
  184.  
  185.     buf = mfread(inf,4);
  186.     return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
  187. }
  188.  
  189. static putshort(outf,val)
  190. FILE *outf;
  191. unsigned short val;
  192. {
  193.     unsigned char buf[2];
  194.  
  195.     buf[0] = (val>>8);
  196.     buf[1] = (val>>0);
  197.     fwrite(buf,2,1,outf);
  198. }
  199.  
  200. static int putlong(outf,val)
  201. FILE *outf;
  202. unsigned long val;
  203. {
  204.     unsigned char buf[4];
  205.  
  206.     buf[0] = (val>>24);
  207.     buf[1] = (val>>16);
  208.     buf[2] = (val>>8);
  209.     buf[3] = (val>>0);
  210.     return fwrite(buf,4,1,outf);
  211. }
  212.  
  213. static readheader(inf,image)
  214. MFILE *inf;
  215. IMAGE *image;
  216. {
  217.     bzero(image,sizeof(IMAGE));
  218.     image->imagic = getshort(inf);
  219.     image->type = getshort(inf);
  220.     image->dim = getshort(inf);
  221.     image->xsize = getshort(inf);
  222.     image->ysize = getshort(inf);
  223.     image->zsize = getshort(inf);
  224. }
  225.  
  226. static int writeheader(outf,image)
  227. FILE *outf;
  228. IMAGE *image;
  229. {
  230.     IMAGE t;
  231.  
  232.     bzero(&t,sizeof(IMAGE));
  233.     fwrite(&t,sizeof(IMAGE),1,outf);
  234.     fseek(outf,0,SEEK_SET);
  235.     putshort(outf,image->imagic);
  236.     putshort(outf,image->type);
  237.     putshort(outf,image->dim);
  238.     putshort(outf,image->xsize);
  239.     putshort(outf,image->ysize);
  240.     putshort(outf,image->zsize);
  241.     putlong(outf,image->min);
  242.     putlong(outf,image->max);
  243.     putlong(outf,0);
  244.     return fwrite("no name",8,1,outf);
  245. }
  246.  
  247. static int writetab(outf,tab,len)
  248. FILE *outf;
  249. unsigned long *tab;
  250. int len;
  251. {
  252.     int r;
  253.  
  254.     while(len) {
  255.     r = putlong(outf,*tab++);
  256.     len -= 4;
  257.     }
  258.     return r;
  259. }
  260.  
  261. static readtab(inf,tab,len)
  262. MFILE *inf;
  263. unsigned long *tab;
  264. int len;
  265. {
  266.     while(len) {
  267.     *tab++ = getlong(inf);
  268.     len -= 4;
  269.     }
  270. }
  271.  
  272. /*
  273.  *    sizeofimage - 
  274.  *        return the xsize and ysize of an iris image file.
  275.  *
  276.  */
  277. sizeofimage(name, xsize, ysize)
  278. char *name;
  279. int *xsize, *ysize;
  280. {
  281.     IMAGE image;
  282.     MFILE *inf;
  283.  
  284.     inf = mfopen(name,"r");
  285.     if(!inf) {
  286.     fprintf(stderr,"sizeofimage: can't open image file %s\n",name);
  287.     exit(1);
  288.     }
  289.     readheader(inf,&image);
  290.     if(image.imagic != IMAGIC) {
  291.     fprintf(stderr,"sizeofimage: bad magic number in image file %s\n",name);
  292.     exit(1);
  293.     }
  294.     *xsize = image.xsize;
  295.     *ysize = image.ysize;
  296.     mfclose(inf);
  297. }
  298.  
  299. /*
  300.  *      sizeofimage3 -
  301.  *              return xsize, ysize and zsize of an iris image file.
  302.  *
  303.  */
  304. sizeofimage3(name, xsize, ysize, zsize)
  305. char *name;
  306. int *xsize, *ysize, *zsize;
  307. {
  308.     IMAGE image;
  309.     MFILE *inf;
  310.  
  311.     inf = mfopen(name,"r");
  312.     if(!inf) {
  313.         fprintf(stderr,"sizeofimage3: can't open image file %s\n",name);
  314.         exit(1);
  315.     }
  316.     readheader(inf,&image);
  317.     if(image.imagic != IMAGIC) {
  318.         fprintf(stderr,"sizeofimage3: bad magic number in image file\n");
  319.         exit(1);
  320.     }
  321.     *xsize = image.xsize;
  322.     *ysize = image.ysize;
  323.     *zsize = image.zsize;
  324.     mfclose(inf);
  325. }
  326.  
  327. /*
  328.  *    longimagedata - 
  329.  *        read in a B/W RGB or RGBA iris image file and return a 
  330.  *    pointer to an array of longs.
  331.  *
  332.  */
  333. unsigned long *longimagedata(name)
  334. char *name;
  335. {
  336.     unsigned long *base, *lptr;
  337.     unsigned char *rledat, *verdat;
  338.     long *starttab, *lengthtab;
  339.     MFILE *inf;
  340.     IMAGE *image;
  341.     int y, z, pos, len, tablen;
  342.     int xsize, ysize, zsize;
  343.     int bpp, rle, cur, badorder;
  344.     int rlebuflen;
  345.  
  346.     inf = mfopen(name,"r");
  347.     if(!inf) {
  348.     fprintf(stderr,"longimagedata: can't open image file %s\n",name);
  349.     exit(1);
  350.     }
  351.     image = (IMAGE *)mymalloc(sizeof(IMAGE));
  352.     readheader(inf,image);
  353.     if(image->imagic != IMAGIC) {
  354.     fprintf(stderr,"longimagedata: bad magic number in image file %s\n",name);
  355.     exit(1);
  356.     }
  357.     rle = ISRLE(image->type);
  358.     bpp = BPP(image->type);
  359.     if(bpp != 1 ) {
  360.     fprintf(stderr,"longimagedata: image must have 1 byte per pix chan\n");
  361.     exit(1);
  362.     }
  363.     xsize = image->xsize;
  364.     ysize = image->ysize;
  365.     zsize = image->zsize;
  366.     if(rle) {
  367.     tablen = ysize*zsize*sizeof(long);
  368.     starttab = (long *)mymalloc(tablen);
  369.     lengthtab = (long *)mymalloc(tablen);
  370.     rlebuflen = 1.05*xsize+10;
  371.     mfseek(inf,512);
  372.      readtab(inf,starttab,tablen);
  373.     readtab(inf,lengthtab,tablen);
  374.  
  375. /* check data order */
  376.     cur = 0;
  377.     badorder = 0;
  378.     for(y=0; y<ysize; y++) {
  379.         for(z=0; z<zsize; z++) {
  380.         if(starttab[y+z*ysize]<cur) {
  381.             badorder = 1;
  382.             break;
  383.         }
  384.         cur = starttab[y+z*ysize];
  385.         }
  386.         if(badorder) 
  387.         break;
  388.     }
  389.  
  390.     mfseek(inf,512+2*tablen);
  391.     cur = 512+2*tablen;
  392.     base = (unsigned long *)
  393.         mymalloc((xsize*ysize+TAGLEN)*sizeof(long));
  394.     addlongimgtag(base,xsize,ysize);
  395.       if(badorder) {
  396.         for(z=0; z<zsize; z++) {
  397.         lptr = base;
  398.         for(y=0; y<ysize; y++) {
  399.             if(cur != starttab[y+z*ysize]) {
  400.             mfseek(inf,starttab[y+z*ysize]);
  401.             cur = starttab[y+z*ysize];
  402.             }
  403.             if(lengthtab[y+z*ysize]>rlebuflen) {
  404.             fprintf(stderr,"longimagedata: rlebuf is too small - bad poop\n");
  405.             exit(1);
  406.             }
  407.             rledat = mfread(inf,lengthtab[y+z*ysize]);
  408.             cur += lengthtab[y+z*ysize];
  409.             expandrow(lptr,rledat,3-z);
  410.             lptr += xsize;
  411.         }
  412.         }
  413.     } else {
  414.         lptr = base;
  415.         for(y=0; y<ysize; y++) {
  416.         for(z=0; z<zsize; z++) {
  417.             if(cur != starttab[y+z*ysize]) {
  418.             mfseek(inf,starttab[y+z*ysize]);
  419.             cur = starttab[y+z*ysize];
  420.             }
  421.             rledat = mfread(inf,lengthtab[y+z*ysize]);
  422.             cur += lengthtab[y+z*ysize];
  423.             expandrow(lptr,rledat,3-z);
  424.         }
  425.         lptr += xsize;
  426.         }
  427.         }
  428.     if(zsize == 3) 
  429.         setalpha(base,xsize*ysize);
  430.     else if(zsize<3) 
  431.         copybw(base,xsize*ysize);
  432.     mfclose(inf);
  433.     free(starttab);
  434.     free(lengthtab);
  435.     free(image);
  436.     return base;
  437.     } else {
  438.     base = (unsigned long *)
  439.         mymalloc((xsize*ysize+TAGLEN)*sizeof(long));
  440.     addlongimgtag(base,xsize,ysize);
  441.     mfseek(inf,512);
  442.     for(z=0; z<zsize; z++) {
  443.         lptr = base;
  444.         for(y=0; y<ysize; y++) {
  445.         verdat = mfread(inf,xsize);
  446.         interleaverow(lptr,verdat,3-z,xsize);
  447.         lptr += xsize;
  448.         }
  449.     }
  450.     if(zsize == 3) 
  451.         setalpha(base,xsize*ysize);
  452.     else if(zsize<3) 
  453.         copybw(base,xsize*ysize);
  454.     mfclose(inf);
  455.     free(image);
  456.     return base;
  457.     }
  458. }
  459.  
  460. /* static utility functions for longimagedata */
  461.  
  462. static interleaverow(lptr,cptr,z,n)
  463. unsigned char *lptr, *cptr;
  464. int z, n;
  465. {
  466.     lptr += z;
  467.     while(n--) {
  468.     *lptr = *cptr++;
  469.     lptr += 4;
  470.     }
  471. }
  472.  
  473. static copybw(lptr,n)
  474. long *lptr;
  475. int n;
  476. {
  477.     while(n>=8) {
  478.     lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
  479.     lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
  480.     lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
  481.     lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
  482.     lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
  483.     lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
  484.     lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
  485.     lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
  486.     lptr += 8;
  487.     n-=8;
  488.     }
  489.     while(n--) {
  490.     *lptr = 0xff000000+(0x010101*(*lptr&0xff));
  491.     lptr++;
  492.     }
  493. }
  494.  
  495. static setalpha(lptr,n)
  496. unsigned char *lptr;
  497. {
  498.     while(n>=8) {
  499.     lptr[0*4] = 0xff;
  500.     lptr[1*4] = 0xff;
  501.     lptr[2*4] = 0xff;
  502.     lptr[3*4] = 0xff;
  503.     lptr[4*4] = 0xff;
  504.     lptr[5*4] = 0xff;
  505.     lptr[6*4] = 0xff;
  506.     lptr[7*4] = 0xff;
  507.     lptr += 4*8;
  508.     n -= 8;
  509.     }
  510.     while(n--) {
  511.     *lptr = 0xff;
  512.     lptr += 4;
  513.     }
  514. }
  515.  
  516. static expandrow(optr,iptr,z)
  517. unsigned char *optr, *iptr;
  518. int z;
  519. {
  520.     unsigned char pixel, count;
  521.  
  522.     optr += z;
  523.     while(1) {
  524.     pixel = *iptr++;
  525.     if ( !(count = (pixel & 0x7f)) )
  526.         return;
  527.     if(pixel & 0x80) {
  528.         while(count>=8) {
  529.         optr[0*4] = iptr[0];
  530.         optr[1*4] = iptr[1];
  531.         optr[2*4] = iptr[2];
  532.         optr[3*4] = iptr[3];
  533.         optr[4*4] = iptr[4];
  534.         optr[5*4] = iptr[5];
  535.         optr[6*4] = iptr[6];
  536.         optr[7*4] = iptr[7];
  537.         optr += 8*4;
  538.         iptr += 8;
  539.         count -= 8;
  540.         }
  541.         while(count--) {
  542.         *optr = *iptr++;
  543.         optr+=4;
  544.         }
  545.     } else {
  546.         pixel = *iptr++;
  547.         while(count>=8) {
  548.         optr[0*4] = pixel;
  549.         optr[1*4] = pixel;
  550.         optr[2*4] = pixel;
  551.         optr[3*4] = pixel;
  552.         optr[4*4] = pixel;
  553.         optr[5*4] = pixel;
  554.         optr[6*4] = pixel;
  555.         optr[7*4] = pixel;
  556.         optr += 8*4;
  557.         count -= 8;
  558.         }
  559.         while(count--) {
  560.         *optr = pixel;
  561.         optr+=4;
  562.         }
  563.     }
  564.     }
  565. }
  566.  
  567. /*
  568.  *    longstoimage -
  569.  *        copy an array of longs to an iris image file.  Each long
  570.  *    represents one pixel.  xsize and ysize specify the dimensions of
  571.  *    the pixel array.  zsize specifies what kind of image file to
  572.  *    write out.  if zsize is 1, the luminance of the pixels are
  573.  *    calculated, and a sinlge channel black and white image is saved.
  574.  *    If zsize is 3, an RGB image file is saved.  If zsize is 4, an
  575.  *    RGBA image file is saved.
  576.  *
  577.  */
  578. int longstoimage(lptr,xsize,ysize,zsize,name)
  579. unsigned long *lptr;
  580. int xsize, ysize, zsize;
  581. char *name;
  582. {
  583.     FILE *outf;
  584.     IMAGE *image;
  585.     int tablen, y, z, pos, len;
  586.     long *starttab, *lengthtab;
  587.     unsigned char *rlebuf;
  588.     unsigned long *lumbuf;
  589.     int rlebuflen, goodwrite;
  590.  
  591.     goodwrite = 1;
  592.     outf = fopen(name,"w");
  593.     if(!outf) {
  594.     fprintf(stderr,"longstoimage: can't open output file\n");
  595.     return 0;
  596.     }
  597.     tablen = ysize*zsize*sizeof(long);
  598.  
  599.     image = (IMAGE *)mymalloc(sizeof(IMAGE));
  600.     starttab = (long *)mymalloc(tablen);
  601.     lengthtab = (long *)mymalloc(tablen);
  602.     rlebuflen = 1.05*xsize+10;
  603.     rlebuf = (unsigned char *)mymalloc(rlebuflen);
  604.     lumbuf = (unsigned long *)mymalloc(xsize*sizeof(long));
  605.  
  606.     bzero(image,sizeof(IMAGE));
  607.     image->imagic = IMAGIC; 
  608.     image->type = RLE(1);
  609.     if(zsize>1)
  610.     image->dim = 3;
  611.     else
  612.     image->dim = 2;
  613.     image->xsize = xsize;
  614.     image->ysize = ysize;
  615.     image->zsize = zsize;
  616.     image->min = 0;
  617.     image->max = 255;
  618.     goodwrite *= writeheader(outf,image);
  619.     fseek(outf,512+2*tablen,SEEK_SET);
  620.     pos = 512+2*tablen;
  621.     for(y=0; y<ysize; y++) {
  622.     for(z=0; z<zsize; z++) {
  623.         if(zsize == 1) {
  624.         lumrow(lptr,lumbuf,xsize);
  625.         len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),xsize);
  626.         } else {
  627.         len = compressrow(lptr,rlebuf,CHANOFFSET(z),xsize);
  628.         }
  629.         if(len>rlebuflen) {
  630.         fprintf(stderr,"longstoimage: rlebuf is too small - bad poop\n");
  631.         exit(1);
  632.         }
  633.         goodwrite *= fwrite(rlebuf,len,1,outf);
  634.         starttab[y+z*ysize] = pos;
  635.         lengthtab[y+z*ysize] = len;
  636.         pos += len;
  637.     }
  638.     lptr += xsize;
  639.     }
  640.  
  641.     fseek(outf,512,SEEK_SET);
  642.     goodwrite *= writetab(outf,starttab,tablen);
  643.     goodwrite *= writetab(outf,lengthtab,tablen);
  644.     free(image);
  645.     free(starttab);
  646.     free(lengthtab);
  647.     free(rlebuf);
  648.     free(lumbuf);
  649.     fclose(outf);
  650.     if(goodwrite)
  651.     return 1;
  652.     else {
  653.     fprintf(stderr,"longstoimage: not enough space for image!!\n");
  654.     return 0;
  655.     }
  656. }
  657.  
  658. /* static utility functions for longstoimage */
  659.  
  660. static lumrow(rgbptr,lumptr,n) 
  661. unsigned char *rgbptr, *lumptr;
  662. int n;
  663. {
  664.     lumptr += CHANOFFSET(0);
  665.     while(n--) {
  666.     *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
  667.     lumptr += 4;
  668.     rgbptr += 4;
  669.     }
  670. }
  671.  
  672. static int compressrow(lbuf,rlebuf,z,cnt)
  673. unsigned char *lbuf, *rlebuf;
  674. int z, cnt;
  675. {
  676.     unsigned char *iptr, *ibufend, *sptr, *optr;
  677.     short todo, cc;                            
  678.     long count;
  679.  
  680.     lbuf += z;
  681.     iptr = lbuf;
  682.     ibufend = iptr+cnt*4;
  683.     optr = rlebuf;
  684.  
  685.     while(iptr<ibufend) {
  686.     sptr = iptr;
  687.     iptr += 8;
  688.     while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
  689.         iptr+=4;
  690.     iptr -= 8;
  691.     count = (iptr-sptr)/4;
  692.     while(count) {
  693.         todo = count>126 ? 126:count;
  694.         count -= todo;
  695.         *optr++ = 0x80|todo;
  696.         while(todo>8) {
  697.         optr[0] = sptr[0*4];
  698.         optr[1] = sptr[1*4];
  699.         optr[2] = sptr[2*4];
  700.         optr[3] = sptr[3*4];
  701.         optr[4] = sptr[4*4];
  702.         optr[5] = sptr[5*4];
  703.         optr[6] = sptr[6*4];
  704.         optr[7] = sptr[7*4];
  705.         optr += 8;
  706.         sptr += 8*4;
  707.         todo -= 8;
  708.         }
  709.         while(todo--) {
  710.         *optr++ = *sptr;
  711.         sptr += 4;
  712.         }
  713.     }
  714.     sptr = iptr;
  715.     cc = *iptr;
  716.     iptr += 4;
  717.     while( (iptr<ibufend) && (*iptr == cc) )
  718.         iptr += 4;
  719.     count = (iptr-sptr)/4;
  720.     while(count) {
  721.         todo = count>126 ? 126:count;
  722.         count -= todo;
  723.         *optr++ = todo;
  724.         *optr++ = cc;
  725.     }
  726.     }
  727.     *optr++ = 0;
  728.     return optr - (unsigned char *)rlebuf;
  729. }
  730.  
  731. #ifdef TESTMAIN
  732.  
  733. #define NTIMES    (1)
  734. /*
  735.  *    this reads in an image and writes it out, and then
  736.  *    uses ipaste to display the converted image file.
  737.  *
  738.  */
  739. main(argc,argv)
  740. int argc;
  741. char **argv;
  742. {
  743.     int xsize, ysize;
  744.     unsigned long *lbuf;
  745. int i;
  746.  
  747.     if(argc<2) {
  748.     fprintf(stderr,"usage: fastimg: inimage.rgb\n");
  749.     exit(1);
  750.     }
  751.     sizeofimage(argv[1],&xsize,&ysize);
  752.  
  753.     lbuf = 0;
  754. system("date");
  755. printf("NEW\n");
  756.  
  757.     for(i=0; i<NTIMES; i++) {
  758.          if(lbuf)
  759.         free(lbuf);
  760.     lbuf = mylongimagedata(argv[1]);
  761.     }
  762. printf("DONE\n");
  763. system("date");
  764.     longstoimage(lbuf,xsize,ysize,3,"/usr/tmp/a.rgb");
  765. system("date");
  766. printf("OLD\n");
  767.     for(i=0; i<NTIMES; i++) {
  768.          if(lbuf)
  769.         free(lbuf);
  770.     lbuf = (unsigned long*)longimagedata(argv[1]);
  771.     }
  772. printf("DONE\n");
  773. system("date");
  774.     longstoimage(lbuf,xsize,ysize,3,"/usr/tmp/t.rgb");
  775.     system("ipaste /usr/tmp/t.rgb");
  776.     system("ipaste /usr/tmp/a.rgb");
  777. }
  778. #endif
  779.